package org.biubiu0002.baiblog.im.async.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.base.Preconditions;
import com.rabbitmq.client.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.biubiu0002.baiblog.im.api.ConversationApiService;
import org.biubiu0002.baiblog.im.api.MessageApiService;
import org.biubiu0002.baiblog.im.async.event.SendChatMsgEvent;
import org.biubiu0002.baiblog.im.config.RabbitMqConfig;
import org.biubiu0002.baiblog.im.constants.MessageConstants;
import org.biubiu0002.baiblog.im.dto.message.MessageResponse;
import org.biubiu0002.baiblog.im.session.ServerSession;
import org.biubiu0002.baiblog.im.session.SessionMap;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * @Author: biubiu0002
 * @Date: 2022/10/25 12:27
 **/
@Component
@Slf4j
@RabbitListener(queues = RabbitMqConfig.SEND_CHAT_MSG_QUEUE)
public class SendChatMsgListener {

    @Resource
    private SessionMap sessionMap;

    @DubboReference
    private MessageApiService messageApiService;

    @DubboReference
    private ConversationApiService conversationApiService;

    @RabbitHandler
    public void onMessage(String msg, Channel channel, Message message) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            Preconditions.checkArgument(StringUtils.isNotBlank(msg));
            log.info("收到发送消息的信息 {}",msg);
            SendChatMsgEvent sendChatMsgEvent = JSON.parseObject(msg, new TypeReference<SendChatMsgEvent>() {
            });
            org.biubiu0002.baiblog.im.dto.message.Message chatMsg = sendChatMsgEvent.getMessage();
            Integer type = chatMsg.getMessageRequest().getType();
            String sessionId = chatMsg.getSessionId();
            ServerSession session = sessionMap.getSession(sessionId);
            if(type.equals(MessageConstants.MessageCommandType.PRIVATE_MESSAGE)){
                //存入到消息数据表
                messageApiService.savePrivateChatMsg(chatMsg);
                //落库后 给客户端返回ACK
                org.biubiu0002.baiblog.im.dto.message.Message ackMessage = this.buildAckMessage(chatMsg, sessionId);
                TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(JSON.toJSONString(ackMessage));
                session.getChannel().writeAndFlush(textWebSocketFrame);
                //更新用户的会话列表 插入最新记录
                conversationApiService.updateLatestMessage(chatMsg);
            }
            else if(type.equals(MessageConstants.MessageCommandType.GROUP_MESSAGE)){
                //存入到消息数据表
                messageApiService.saveGroupChatMsg(chatMsg);
                //落库后 给客户端返回ACK NOTIFY
                org.biubiu0002.baiblog.im.dto.message.Message ackMessage = this.buildAckMessage(chatMsg, sessionId);
                TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(JSON.toJSONString(ackMessage));
                session.getChannel().writeAndFlush(textWebSocketFrame);
                //更新群聊中所有用户的会话列表 插入最新记录
                conversationApiService.updateLatestMessage(chatMsg);

            }



            channel.basicAck(deliveryTag,false);


        }catch (Exception e){
            if (Boolean.TRUE.equals(message.getMessageProperties().isRedelivered())) {
                log.error("[消费拒绝]:{}",message,e);
                channel.basicReject(deliveryTag,false);
            }else{
                log.warn("[消费重试]:{}",message,e);
                channel.basicNack(deliveryTag,false,true);
            }

        }

    }

    private org.biubiu0002.baiblog.im.dto.message.Message buildAckMessage(org.biubiu0002.baiblog.im.dto.message.Message chatMsg, String sessionId) {
        org.biubiu0002.baiblog.im.dto.message.Message ackMessage = new org.biubiu0002.baiblog.im.dto.message.Message();
        ackMessage.setType(MessageConstants.MessageType.RESPONSE);
        ackMessage.setSessionId(sessionId);
        MessageResponse messageResponse = new MessageResponse();
        messageResponse.setType(MessageConstants.MessageResponseType.ACK);
        messageResponse.setAckMsgId(chatMsg.getMessageRequest().getMsgId());
        messageResponse.setAckMsgIdStr(String.valueOf(chatMsg.getMessageRequest().getMsgId()));
        ackMessage.setMessageResponse(messageResponse);
        return ackMessage;
    }
}
